import json
import string
import random

import requests
from sqlalchemy import Column, Integer, String, Boolean, Float, ForeignKey, UniqueConstraint, Index, orm, DECIMAL
from sqlalchemy.dialects.mysql import LONGTEXT

from app.libs.enums import Scope_dict
from app.libs.error_code import NotFoundUser
from app.libs.tools import generate_random_name
from app.models.base import Base, db


class User(Base):
    id = Column(Integer, autoincrement=True, primary_key=True)
    nickname = Column(String(50), default='')
    avatar = Column(String(100), default='')
    gzh_open_id = Column(String(100), default='')
    mp_open_id = Column(String(100), default='')
    union_id = Column(String(100), default='')
    remain = Column(Integer, default=0)
    role_id = Column(Integer, default=5)
    amount = Column(DECIMAL(9, 2), default=0)
    free_chars = Column(Integer, default=0)
    recommender = Column(String(100), default=0)
    scene = Column(Integer, default=0)

    def keys(self):
        return ['id', 'nickname', 'avatar', 'gzh_open_id', 'mp_open_id', 'union_id', 'amount', 'free_chars',
                'recommender']

    @staticmethod
    def verify_by_wxpro(account, password, wx_open_id='', wx_union_id='', scene=0):
        sdk_url = 'https://api.weixin.qq.com/sns/jscode2session'
        code = account
        params = {
            'appid': 'wxe714527bc5c7ec08',
            'secret': 'deeb49c705fc7fbfcf73fa3a374b7621',
            'js_code': code,
            'grant_type': 'authorization_code'
        }
        r = requests.get(sdk_url, params)
        if r.status_code == 200:
            openid = r.json()['openid']
            try:
                unionid = r.json()['unionid']
            except:
                unionid = ''
            if unionid == '':
                user = User.query.filter_by(mp_open_id=openid).first()
            else:
                user = User.query.filter_by(union_id=unionid).first()
            if user:
                if user.scene == 0 and scene != 0:
                    with db.auto_commit():
                        User.query.filter_by(union_id=unionid).update({
                            'scene': scene
                        })
                if user.gzh_open_id == '':
                    gzh_open_id = User.getGzhOpenId(unionid)
                    if gzh_open_id != '':
                        with db.auto_commit():
                            User.query.filter_by(mp_open_id=openid).update({
                                'gzh_open_id': gzh_open_id
                            })
                if user.mp_open_id == '':
                    with db.auto_commit():
                        User.query.filter_by(union_id=unionid).update({
                            'mp_open_id': openid
                        })
                return {'uid': user.id, 'scope': Scope_dict[user.role_id]}
            else:
                with db.auto_commit():
                    gzh_open_id = User.getGzhOpenId(unionid)
                    user_model = User()
                    user_model.mp_open_id = openid
                    user_model.union_id = unionid
                    user_model.role_id = 5
                    user_model.nickname = generate_random_name()
                    user_model.gzh_open_id = gzh_open_id
                    user_model.scene = scene
                    db.session.add(user_model)
                    db.session.flush()
                    return {'uid': user_model.id, 'scope': Scope_dict[user_model.role_id]}

    @staticmethod
    def verify_by_scan(account, password, wx_open_id='', wx_union_id='', scene=0):
        unionid = account
        user = User.query.filter_by(union_id=unionid).first()
        if user:
            if user.scene == 0 and scene != 0:
                with db.auto_commit():
                    User.query.filter_by(union_id=unionid).update({
                        'scene': scene
                    })
            if user.gzh_open_id == '':
                gzh_open_id = User.getGzhOpenId(unionid)
                if gzh_open_id != '':
                    with db.auto_commit():
                        User.query.filter_by(union_id=unionid).update({
                            'gzh_open_id': gzh_open_id
                        })
            return {'uid': user.id, 'scope': Scope_dict[user.role_id]}
        else:
            with db.auto_commit():
                gzh_open_id = User.getGzhOpenId(unionid)
                user_model = User()
                user_model.mp_open_id = ''
                user_model.union_id = unionid
                user_model.role_id = 5
                user_model.nickname = generate_random_name()
                user_model.gzh_open_id = gzh_open_id
                user_model.scene = scene
                db.session.add(user_model)
                db.session.flush()
                return {'uid': user_model.id, 'scope': Scope_dict[user_model.role_id]}

    @staticmethod
    def getGzhOpenId(unionid):
        data = {
            'unionid': unionid
        }
        headers = {
            "Content-Type": "application/json"
        }
        r = requests.post('http://api.samereport.com/v1/gzh/receiver/gzhopenid', data=json.dumps(data), headers=headers)
        if r.status_code == 200:
            data = json.loads(r.text)
            gzh_open_id = data['gzh_open_id']
            return gzh_open_id
        return ''